Typical HAL HASH use cases for migration

This section provides information about typical HAL HASH use cases for migration.

  • HAL1 uses separate processing functions for each hash algorithm to perform HASH or HMAC computation. HAL2 is designed with unified APIs where the desired algorithm is selected through a configuration function.

  • The HASH driver supports two processing flows: one-shot processing of a single buffer, and multi-buffer processing where the user updates multiple buffers incrementally before producing the final digest.

  • The HASH driver supports suspending an ongoing HASH or HMAC computation. When a suspend request occurs, the HASH processing context must be saved and restored before resuming from the correct point.

  • The use cases below are applicable not only to the HASH process with the SHA1 algorithm, but also extend to other hash algorithms such as MD5, SHA224, SHA256, and SHA384. These examples are also relevant for HMAC operations.


Use case: HASH process using SHA1 algorithm in polling mode

Sequence diagram

HASH process

  @startuml
    participant "Application" as App
    participant "HASH" as HASH

    == HASH Initialization and Configuration ==
    App -> HASH: HAL_HASH_Init()
    note right : Configure the data type
    App <-- HASH:\n\n
    ==  HASH process with SHA1 algorithm  ==
    group process: oneshot computing with single buffer
    App -> HASH: HAL_HASH_SHA1_Start()
    note right : Compute and read the digest \nfrom the output buffer \nprovided via a pointer
    end
    group process: computing with several input buffers
    App -> HASH: HAL_HASH_SHA1_Accmlt()
    note right : write the first input buffer
    App -> HASH: HAL_HASH_SHA1_Accmlt()
    note right : write the next input buffer
    App -> HASH: HAL_HASH_SHA1_Accmlt_End()
    note right : - feed the last input data buffer \n - retrieve the computed digest \nreturned via a pointer
    end

    == HASH De-initialization  ==
    App -> HASH: HAL_HASH_DeInit()

  @enduml

HMAC process

  @startuml
  participant "Application" as App
  participant "HASH" as HASH

  == HASH initialization and Configuration ==
  App -> HASH: HAL_HASH_Init()
  note right : Configure the data type,\n key and key size
  App <-- HASH:\n\n\n
  ==  HASH process with SHA1 algorithm  ==
  group process: oneshot computing with single buffer
  App -> HASH: HAL_HMAC_SHA1_Start()
  note right : Compute and read the digest from \nthe output buffer provided via a pointer
  end
  group process: computing with several input buffers


  note right App: HAL1 does not support computing multi-buffers with HMAC process in polling mode
  App <-- HASH:\n\n\n\n\n\n\n
  end

  == HASH De-initialization  ==
  App -> HASH: HAL_HASH_DeInit()

  @enduml

Code snippet

HAL1

HAL2

/* This example is used with HASH processing */

 uint8_t Msg65_Input[65] __attribute__ ((aligned (128)))= {
 0x52, 0x43, 0x31, 0x5f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
 0x61, 0x50, 0x72, 0x6f, 0x6a, 0x65,0x63, 0x74, 0x5f, 0x53,
 0x46, 0x55, 0x61, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
 0x73, 0x61,0x53, 0x54, 0x4d, 0x33, 0x32, 0x32, 0x78, 0x47,
 0x2d, 0x45, 0x56, 0x41, 0x4c, 0x61, 0x45, 0x57, 0x41, 0x52,
 0x4d, 0x61, 0x53, 0x54, 0x4d, 0x33, 0x32, 0x32, 0x78, 0x47,
 0x5f, 0x45, 0x56, 0x41, 0x4c};
 uint8_t Sha1output[20]={0};


 /* HASH Initialization and configuration */
 hhash.Init.DataType = HASH_DATATYPE_8B;
 HAL_HASH_Init(&hhash);




 /* Process with oneshot HASH computing SHA1 algorithm */




 HAL_HASH_SHA1_Start(&hhash, Msg65_Input, 65, Sha1output, 1);

 /* Process with multi-buffer updating to compute SHA1 algorithm */





 HAL_HASH_SHA1_Accmlt(&hhash, Msg65_Input, 29);
 HAL_HASH_SHA1_Accmlt(&hhash, Msg65_Input+29, 33);
 HAL_HASH_SHA1_Accmlt_End(&hhash, Msg65_Input+62, 3, Sha1output, 1);

 /* De-initialization */
 HAL_HASH_DeInit(&hhash);
/* This example is used with HASH processing */

 uint8_t Msg65_Input[65] __attribute__ ((aligned (128)))= {
 0x52, 0x43, 0x31, 0x5f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
 0x61, 0x50, 0x72, 0x6f, 0x6a, 0x65,0x63, 0x74, 0x5f, 0x53,
 0x46, 0x55, 0x61, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
 0x73, 0x61,0x53, 0x54, 0x4d, 0x33, 0x32, 0x32, 0x78, 0x47,
 0x2d, 0x45, 0x56, 0x41, 0x4c, 0x61, 0x45, 0x57, 0x41, 0x52,
 0x4d, 0x61, 0x53, 0x54, 0x4d, 0x33, 0x32, 0x32, 0x78, 0x47,
 0x5f, 0x45, 0x56, 0x41, 0x4c};
 uint8_t Sha1output[20]={0};
 uint32_t sha1output_size;

 /* HASH Initialization */
 HAL_HASH_Init(&hhash, HAL_HASH);
 /* Configure SHA1 algorithm */
 hash_cfg.data_swapping  = HAL_HASH_DATA_SWAP_BYTE;
 hash_cfg.algorithm = HAL_HASH_ALGO_SHA1;
 HAL_HASH_SetConfig(&hhash, &hash_cfg);

 /* Process with oneshot HASH computing SHA1 algorithm */
 /* When the input buffer size is not a multiple of the word size,
    the last word of the message fed to the hash processor will be
    configured by considering only the valid bits specified by NBLW */

 HAL_HASH_Compute(&hhash, Msg65_Input, 65, Sha1output, 20, &sha1output_size, 1);

 /* Process with multi-buffer updating to compute SHA1 algorithm */
 /* When the input buffer size is not a multiple of the word size,
    the remaining bytes of the last word of the current message will be
    stored in the handle and processed with the next update operation */

 HAL_HASH_Update(&hhash, Msg65_Input, 29, 1);
 HAL_HASH_Update(&hhash, Msg65_Input+29, 33, 1);
 HAL_HASH_Update(&hhash, Msg65_Input+62, 3, 1);
 HAL_HASH_Finish(&hhash, Sha1output, 20, &sha1output_size, 1);
 /* De-initialization */
 HAL_HASH_DeInit(&hhash);

Key changes

  1. HAL2 uses unified HASH APIs (compute/update/finish) and selects the algorithm through a configuration function.

  2. HAL2 supports multi-buffer HMAC in polling mode, while HAL1 supports only one-shot HMAC in polling mode.


Use case: HASH process using SHA1 algorithm in IT mode

Sequence diagram

HASH process

  @startuml
  participant "Application" as App
  participant "HASH" as HASH
  participant "NVIC" as nvic

  == HASH initialization and Configuration ==
  App -> HASH: HAL_HASH_Init()
  note right : Configure the data type
  App <-- HASH:\n\n
  ==  HASH process with SHA1 algorithm ==
  group process: oneshot computing with single buffer
  App -> HASH: HAL_HASH_SHA1_Start_IT()
  note right : Compute and read the digest \nfrom the output buffer \n provided via a pointer
  nvic-> HASH : HAL_HASH_IRQHandler()
  App <-- HASH : HAL_HASH_DgstCpltCallback()
  end
  group process: computing with several input buffers
  App -> HASH: HAL_HASH_SHA1_Accmlt_IT()
  note right : write the first input buffer
  nvic-> HASH : HAL_HASH_IRQHandler()
  App->HASH : HAL_HASH_InCpltCallback()
  App -> HASH: HAL_HASH_SHA1_Accmlt_End_IT()
  note right :- feed the last input data buffer \n \n -retrieve the computed digest \nreturned via a pointer
  nvic-> HASH : HAL_HASH_IRQHandler()
  App->HASH : HAL_HASH_InCpltCallback() \n HAL_HASH_DgstCpltCallback()

  end
  App <-- HASH:\n\n\n\n
  == HASH De-initialization  ==
  App -> HASH: HAL_HASH_DeInit()

  @enduml

HMAC process

  @startuml
  participant "Application" as App
  participant "HASH" as HASH
  participant "NVIC" as nvic

  == HASH initialization and Configuration ==
  App -> HASH: HAL_HASH_Init()
  note right : Configure the data type,\n key and key size
  App <-- HASH:\n
  ==  HASH process with SHA1 algorithm ==
  group process: oneshot computing with single buffer
  App -> HASH: HAL_HMAC_SHA1_Start_IT()
  note right : Compute and read the digest \n from the output buffer \n provided via a pointer
  nvic-> HASH : HAL_HASH_IRQHandler()
  App <-- HASH : HAL_HASH_DgstCpltCallback()
  end

  group process: computing with several input buffers


  note over App, nvic: HAL1 does not support computing \n multi-buffers with HMAC process in IT mode
  App <-- HASH:\n\n\n\n\n\n\n\n\n\n\n
  end
  App <-- HASH:\n\n\n\n\n\n\n\n
  == HASH De-initialization  ==
  App -> HASH: HAL_HASH_DeInit()

  @enduml

Code snippet

HAL1

HAL2

/* This example is used with HASH processing mode */

uint8_t Msg65_Input[65] __attribute__ ((aligned (128)))= {
0x52, 0x43, 0x31, 0x5f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
0x61, 0x50, 0x72, 0x6f, 0x6a, 0x65,0x63, 0x74, 0x5f, 0x53,
0x46, 0x55, 0x61, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
0x73, 0x61,0x53, 0x54, 0x4d, 0x33, 0x32, 0x32, 0x78, 0x47,
0x2d, 0x45, 0x56, 0x41, 0x4c, 0x61, 0x45, 0x57, 0x41, 0x52,
0x4d, 0x61, 0x53, 0x54, 0x4d, 0x33, 0x32, 0x32, 0x78, 0x47,
0x5f, 0x45, 0x56, 0x41, 0x4c};
uint8_t Sha1output[20]={0};


/* HASH Initialization and configuration */
hhash.Init.DataType = HASH_DATATYPE_8B;
HAL_HASH_Init(&hhash);




/* Process with oneshot HASH computing SHA1 algorithm */
HAL_HASH_SHA1_Start_IT(&hhash, Msg65_Input, 65, Sha1output);


/* Process with multi-buffer updating to compute SHA1 algorithm */
HAL_HASH_SHA1_Accmlt_IT(&hhash, Msg65_Input, 60);
/* Wait for input completion callback */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_READY);
/* Feed the last input data buffer to the peripheral and retrieve the digest */
HAL_HASH_SHA1_Accmlt_End_IT(&hhash, Msg65_Input+60, 5, Sha1output);
/* Wait for digest computation completed callback */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_READY);




/* De-initialization */
HAL_HASH_DeInit(&hhash);
/* This example is used with HASH processing */

 uint8_t Msg65_Input[65] __attribute__ ((aligned (128)))= {
 0x52, 0x43, 0x31, 0x5f, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65,
 0x61, 0x50, 0x72, 0x6f, 0x6a, 0x65,0x63, 0x74, 0x5f, 0x53,
 0x46, 0x55, 0x61, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65,
 0x73, 0x61,0x53, 0x54, 0x4d, 0x33, 0x32, 0x32, 0x78, 0x47,
 0x2d, 0x45, 0x56, 0x41, 0x4c, 0x61, 0x45, 0x57, 0x41, 0x52,
 0x4d, 0x61, 0x53, 0x54, 0x4d, 0x33, 0x32, 0x32, 0x78, 0x47,
 0x5f, 0x45, 0x56, 0x41, 0x4c};
 uint8_t Sha1output[20]={0};
 uint32_t sha1output_size;

 /* HASH Initialization */
 HAL_HASH_Init(&hhash, HAL_HASH);
 /* Configure SHA1 algorithm */
 hash_cfg.data_swapping  = HAL_HASH_DATA_SWAP_BYTE;
 hash_cfg.algorithm = HAL_HASH_ALGO_SHA1;
 HAL_HASH_SetConfig(&hhash, &hash_cfg);

 /* Process with oneshot HASH computing SHA1 algorithm */
 HAL_HASH_Compute_IT(&hhash, Msg65_Input, 65, Sha1output,
                     20, &sha1output_size);

 /* Process with multi-buffer updating to compute SHA1 algorithm */
 HAL_HASH_Update_IT(&hhash, Msg65_Input, 60);
 /* Wait for input completion callback */
 while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
 /* Feed the last input data buffer to the peripheral */
 HAL_HASH_Update_IT(&hhash, Msg65_Input+60, 5);
 /* Wait for input completion callback */
 while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
 /* Retrieve the digest */
 HAL_HASH_Finish(&hhash, Sha1output, 20, &sha1output_size, 1000);
 /* Wait for digest computation completed callback */
 while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
 /* De-initialization */
 HAL_HASH_DeInit(&hhash);

Key changes

  1. HAL2 uses unified interrupt APIs (compute/update/finish) and uses configuration functions to select the algorithm.

  2. HAL2 uses different completion callbacks (input and digest completion) and supports multi-buffer HMAC in IT mode.


Use case: HASH process using SHA1 algorithm in DMA mode

Sequence diagram

HASH process

  @startuml
  participant "Application" as App
  participant "HASH" as HASH
  participant "NVIC" as nvic
  participant "DMA" as dma

  == HASH initialization and Configuration ==
  App -> HASH: HAL_HASH_Init()
  note right : Configure the data type
  App <-- HASH:\n\n\n\n
  ==   HASH process with SHA1 algorithm  ==
  group process: oneshot computing with single buffer
  App -> HASH: HAL_HASH_SHA1_Start_DMA()
  note right: compute HASH input buffer
  nvic -> dma: HAL_DMA_IRQ_Handler()
  dma -> HASH: DMA Transfer complete
  HASH -> App: HAL_HASH_InputCpltCallback()
  App -> HASH: HAL_HASH_SHA1_Finish()
  note right: retrieve the computed digest \nreturned via a pointer

  end
  group process: computing with several input buffers
  App -> HASH: HAL_HASH_SHA1_Start_DMA()
  note right : write the first input buffer
  nvic -> dma: HAL_DMA_IRQ_Handler()
  dma -> HASH: DMA Transfer complete
  HASH -> App: HAL_HASH_InputCpltCallback()
  App -> HASH: HAL_HASH_SHA1_Start_DMA()
  note right : write the last input buffer
  nvic -> dma: HAL_DMA_IRQ_Handler()
  dma -> HASH: DMA Transfer complete
  HASH -> App: HAL_HASH_InputCpltCallback()
  App -> HASH: HAL_HASH_SHA1_Finish()
  note right: retrieve the computed digest \nreturned via a pointer
  end
  App <-- HASH:\n\n\n
  == HASH De-initialization  ==
  App -> HASH: HAL_HASH_DeInit()
  @enduml

HMAC process

  @startuml
  participant "Application" as App
  participant "HASH" as HASH
  participant "NVIC" as nvic
  participant "DMA" as dma

  == HASH initialization and Configuration ==
  App -> HASH: HAL_HASH_Init()
  note right : Configure the data type,\n key and key size
  App <-- HASH:\n\n\n\n
  ==  HASH process with SHA1 algorithm ==
  group process: oneshot computing with single buffer
  App -> HASH: HAL_HMAC_SHA1_Start_DMA()
  note right: compute HASH input buffer
  nvic -> dma: HAL_DMA_IRQ_Handler()
  dma -> HASH: DMA Transfer complete
  HASH -> App: HAL_HASH_InCpltCallback()
  App -> HASH: HAL_HASH_SHA1_Finish()
  note right: retrieve the computed digest \nreturned via a pointer

  end
  group process: computing with several input buffers
  App -> HASH: HAL_HMACEx_SHA1_Step1_2_DMA()
  note right : write the first input buffer
  nvic -> dma: HAL_DMA_IRQ_Handler()
  dma -> HASH: DMA Transfer complete
  HASH -> App: HAL_HASH_InputCpltCallback()
  App -> HASH: HAL_HMACEx_SHA1_Step2_DMA()
  note right : feed the next input buffer
  nvic -> dma: HAL_DMA_IRQ_Handler()
  dma -> HASH: DMA Transfer complete
  HASH -> App: HAL_HASH_InputCpltCallback()
  App -> HASH: HAL_HMACEx_SHA1_Step2_3_DMA()
  note right : feed the last input buffer to \n the peripheral
  nvic -> dma: HAL_DMA_IRQ_Handler()
  dma -> HASH: DMA Transfer complete
  HASH -> App: HAL_HASH_InputCpltCallback()
  App -> HASH: HAL_HASH_SHA1_Finish()
  note right: retrieve the computed digest \nreturned via a pointer
  end
  == HASH De-initialization  ==
  App -> HASH: HAL_HASH_DeInit()

  @enduml

Code snippet

HAL1

HAL2

/* This example is used with HASH processing */

uint8_t Input[261] =
{0x54,0x68,0x65,0x20,0x68,0x61,0x73,0x68,
0x20,0x70,0x72,0x6f,0x63,0x65,0x73,0x73,
0x6f,0x72,0x20,0x69,0x73,0x20,0x61,0x20,
0x66,0x75,0x6c,0x6c,0x79,0x20,0x63,0x6f,
0x6d,0x70,0x6c,0x69,0x61,0x6e,0x74,0x20,
0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,
0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,
0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x65,
0x63,0x75,0x72,0x65,0x20,0x68,0x61,0x73,
0x68,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69,
0x74,0x68,0x6d,0x20,0x28,0x53,0x48,0x41,
0x2d,0x31,0x29,0x2c,0x20,0x74,0x68,0x65,
0x20,0x4d,0x44,0x35,0x20,0x28,0x6d,0x65,
0x73,0x73,0x61,0x67,0x65,0x2d,0x64,0x69,
0x67,0x65,0x73,0x74,0x20,0x61,0x6c,0x67,
0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x35,
0x29,0x20,0x68,0x61,0x73,0x68,0x20,0x61,
0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,
0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,
0x20,0x48,0x4d,0x41,0x43,0x20,0x28,0x6b,
0x65,0x79,0x65,0x64,0x2d,0x68,0x61,0x73,
0x68,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,
0x65,0x20,0x61,0x75,0x74,0x68,0x65,0x6e,
0x74,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x63,0x6f,0x64,0x65,0x29,0x20,0x61,
0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,
0x20,0x73,0x75,0x69,0x74,0x61,0x62,0x6c,
0x65,0x20,0x66,0x6f,0x72,0x20,0x61,0x20,
0x76,0x61,0x72,0x69,0x65,0x74,0x79,0x20,
0x6f,0x66,0x20,0x61,0x70,0x70,0x6c,0x69,
0x63,0x61,0x74,0x69,0x6f,0x6e,0x73,0x2e,
0x2a,0x2a,0x2a,0x20,0x53,0x54,0x4d,0x33,
0x32,0x20,0x2a,0x2a,0x2a};
uint8_t Sha1output[20]={0};


/* HASH Initialization */
hhash.Instance = HASH;
hhash.Init.DataType = HASH_DATATYPE_8B;
HAL_HASH_Init(&hhash);
__HAL_HASH_SET_MDMAT();




/* Oneshot compute with single input buffer */
HAL_HASH_SHA1_Start_DMA(&hhash, Input, 261);
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
HAL_HASH_SHA1_Finish(&hhash, Sha1output, 1);
while (HAL_HASH_GetState(&hhash) == HAL_HASH_STATE_BUSY);

/* Compute SHA1 with several inputs buffers */
HAL_HASH_SHA1_Start_DMA(&hhash, Input, 128);
while (HAL_HASH_GetState(&hhash) == HAL_HASH_STATE_BUSY);
HAL_HASH_SHA1_Start_DMA(&hhash, Input+192, 64);
while (HAL_HASH_GetState(&hhash) == HAL_HASH_STATE_BUSY);
HAL_HASH_SHA1_Start_DMA(&hhash, Input+256, 5);
__HAL_HASH_RESET_MDMAT();
HAL_HASH_SHA1_Finish(&hhash, Sha1output, 1);
while (HAL_HASH_GetState(&hhash) == HAL_HASH_STATE_BUSY);
/* De-initialization */
HAL_HASH_DeInit(&hhash);
/* This example is used with HASH processing */

uint8_t Input[261] =
{0x54,0x68,0x65,0x20,0x68,0x61,0x73,0x68,
0x20,0x70,0x72,0x6f,0x63,0x65,0x73,0x73,
0x6f,0x72,0x20,0x69,0x73,0x20,0x61,0x20,
0x66,0x75,0x6c,0x6c,0x79,0x20,0x63,0x6f,
0x6d,0x70,0x6c,0x69,0x61,0x6e,0x74,0x20,
0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,
0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,
0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x65,
0x63,0x75,0x72,0x65,0x20,0x68,0x61,0x73,
0x68,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69,
0x74,0x68,0x6d,0x20,0x28,0x53,0x48,0x41,
0x2d,0x31,0x29,0x2c,0x20,0x74,0x68,0x65,
0x20,0x4d,0x44,0x35,0x20,0x28,0x6d,0x65,
0x73,0x73,0x61,0x67,0x65,0x2d,0x64,0x69,
0x67,0x65,0x73,0x74,0x20,0x61,0x6c,0x67,
0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x35,
0x29,0x20,0x68,0x61,0x73,0x68,0x20,0x61,
0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,
0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,
0x20,0x48,0x4d,0x41,0x43,0x20,0x28,0x6b,
0x65,0x79,0x65,0x64,0x2d,0x68,0x61,0x73,
0x68,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,
0x65,0x20,0x61,0x75,0x74,0x68,0x65,0x6e,
0x74,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x63,0x6f,0x64,0x65,0x29,0x20,0x61,
0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,
0x20,0x73,0x75,0x69,0x74,0x61,0x62,0x6c,
0x65,0x20,0x66,0x6f,0x72,0x20,0x61,0x20,
0x76,0x61,0x72,0x69,0x65,0x74,0x79,0x20,
0x6f,0x66,0x20,0x61,0x70,0x70,0x6c,0x69,
0x63,0x61,0x74,0x69,0x6f,0x6e,0x73,0x2e,
0x2a,0x2a,0x2a,0x20,0x53,0x54,0x4d,0x33,
0x32,0x20,0x2a,0x2a,0x2a};
uint8_t Sha1output[20]={0};
uint32_t sha1output_size;

/* HASH Initialization */
hhash.instance = HAL_HASH;
HAL_HASH_Init(&hhash, HAL_HASH);
HAL_HASH_SetInDMA(&hhash, &hdmaIn);
/* Configure SHA1 algorithm */
hash_cfg.data_swapping  = HAL_HASH_DATA_SWAP_BYTE;
hash_cfg.algorithm = HAL_HASH_ALGO_SHA1;
HAL_HASH_SetConfig(&hhash, &hash_cfg);

/* Oneshot compute with single input buffer */
HAL_HASH_Compute_DMA(&hhash, Input, 256, Sha1output, 20, &sha1output_size);
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);



/* Compute SHA1 with several inputs buffers */
HAL_HASH_Update_DMA(&hhash, Input, 128);
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
HAL_HASH_Update_DMA(&hhash, Input+192, 64);
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
HAL_HASH_Update_DMA(&hhash, Input+256, 5);
/* Retrieve the computed digest */
HAL_HASH_Finish(&hhash, Sha1output, 20, &sha1output_size, 1);
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
/* De-initialization */
HAL_HASH_DeInit(&hhash);

Key changes

  1. HAL2 requires linking the DMA handle through a dedicated configuration function and uses unified DMA APIs.

  2. HAL2 uses unified input and digest completion callbacks for DMA transfers.


Use case: HASH process suspending and resuming in IT mode

Sequence diagram

  @startuml
   participant "Application" as App
   participant "HASH " as HASH
   participant "NVIC" as nvic

   == HASH Initialization and Configuration ==
   App->HASH : HAL_HASH_Init()
   note right : Configure the HASH  \n with SHA1 and data swapping
   == Process 1 : Low priority block computing HASH processing IT mode ==
   App->HASH : HAL_HASH_SHA1_Accmlt_IT()
   note right: start processing in IT mode
   App->HASH : HAL_HASH_SwFeed_ProcessSuspend()
   note right: Set the handle field SuspendRequest to the appropriate value so that \
   \n the on-going HASH processing is suspended as soon as the required \
   \nconditions are met \
   \n  Note that on some devices, the suspend request may be performed by calling **HAL_HASH_ProcessSuspend()**
   nvic -> HASH : HAL_HASH_IRQHandler()
   App->HASH : while (HAL_HASH_GetState() == HAL_HASH_STATE_SUSPENDED)
   note right: wait until processing is suspended
   App->HASH : HAL_HASH_ContextSaving()
   note right: - save the HASH context in an allocated buffer memory \n \n - Note that on some devices, the context is saved by calling **HAL_HASH_Suspend()**

   == Process 2 : High priority block computing HMAC processing IT mode ==
   App->HASH : HAL_HASH_Init()
   note right : Configure the HMAC with \n including the key and the key size
   App->HASH : HAL_HMACHEx_SHA256_Start_IT()
   note right : Compute and read the HMAC digest returned via a pointer
   nvic -> HASH : HAL_HASH_IRQHandler()
   HASH -> App: HAL_HASH_DgstCpltCallback()
   == Process 1 : Resuming HASH processing IT mode  ==
   App->HASH : HAL_HASH_ContextRestoring()
   note right : - restore all the context swap registers \n \n - Note that on some devices, the context is restored by calling **HAL_HASH_Resume()**
   nvic -> HASH : HAL_HASH_IRQHandler()
   note right : the previous IT process is resumed
   HASH--> App : HAL_HASH_InCpltCallback()
   App->HASH : HAL_HASH_SHA1_Accmlt_End_IT()
   note right: the HASH peripheral feed the rest of the input buffer \n and retrieve the diest
   nvic -> HASH : HAL_HASH_IRQHandler()
  HASH -> App: HAL_HASH_InCpltCallback() \n HAL_HASH_DgstCpltCallback()
   == HASH De-initialization  ==
   App->HASH : HAL_HASH_DeInit()

  @enduml

Code snippet

HAL1

HAL2

uint8_t Input[261] =
{0x54,0x68,0x65,0x20,0x68,0x61,0x73,0x68,
0x20,0x70,0x72,0x6f,0x63,0x65,0x73,0x73,
0x6f,0x72,0x20,0x69,0x73,0x20,0x61,0x20,
0x66,0x75,0x6c,0x6c,0x79,0x20,0x63,0x6f,
0x6d,0x70,0x6c,0x69,0x61,0x6e,0x74,0x20,
0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,
0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,
0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x65,
0x63,0x75,0x72,0x65,0x20,0x68,0x61,0x73,
0x68,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69,
0x74,0x68,0x6d,0x20,0x28,0x53,0x48,0x41,
0x2d,0x31,0x29,0x2c,0x20,0x74,0x68,0x65,
0x20,0x4d,0x44,0x35,0x20,0x28,0x6d,0x65,
0x73,0x73,0x61,0x67,0x65,0x2d,0x64,0x69,
0x67,0x65,0x73,0x74,0x20,0x61,0x6c,0x67,
0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x35,
0x29,0x20,0x68,0x61,0x73,0x68,0x20,0x61,
0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,
0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,
0x20,0x48,0x4d,0x41,0x43,0x20,0x28,0x6b,
0x65,0x79,0x65,0x64,0x2d,0x68,0x61,0x73,
0x68,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,
0x65,0x20,0x61,0x75,0x74,0x68,0x65,0x6e,
0x74,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x63,0x6f,0x64,0x65,0x29,0x20,0x61,
0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,
0x20,0x73,0x75,0x69,0x74,0x61,0x62,0x6c,
0x65,0x20,0x66,0x6f,0x72,0x20,0x61,0x20,
0x76,0x61,0x72,0x69,0x65,0x74,0x79,0x20,
0x6f,0x66,0x20,0x61,0x70,0x70,0x6c,0x69,
0x63,0x61,0x74,0x69,0x6f,0x6e,0x73,0x2e,
0x2a,0x2a,0x2a,0x20,0x53,0x54,0x4d,0x33,
0x32,0x20,0x2a,0x2a,0x2a};
uint8_t Msg3_Input[3] __attribute__ ((aligned (128)))= {
0x61, 0x62, 0x63};
uint8_t Sha1output[20]={0};
uint8_t Storage_Buffer[57*4] = {0};
HASH_HandleTypeDef hhash_saved;

/* HASH Initialization and configuration */
hhash.Init.DataType =  HASH_DATATYPE_8B;
HAL_HASH_Init(&hhash);




/* process 1 : Low-priority block computing in HASH processing mode  */
HAL_HASH_SHA1_Accmlt_IT(&hhash, Input, 64);
HAL_HASH_SwFeed_ProcessSuspend(&hhash);
/* wait until processing is suspended */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_SUSPENDED);
/* save the context into a raw memory buffer  */
HAL_HASH_ContextSaving(&hhash, Storage_Buffer);
/* save low-priority block HASH handle parameters */
hhash_saved = hhash;

/* process 2: High-priority block computing in HMAC processing mode */
hhash.Init.DataType = HASH_DATATYPE_8B;
hhash.Init.pKey = Input;
hhash.Init.KeySize = 261;
HAL_HASH_Init(&hhash);

HAL_HMACEx_SHA256_Start_IT(&hhash, Msg3_Input, 3, Sha1output);

while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_READY);

/* Resume process 1 */
/* Context restoring operation */
HAL_HASH_ContextRestoring(&hhash, Storage_Buffer);
hhash = hhash_saved;

/* feeding input buffer */
HAL_HASH_SHA1_Accmlt_IT(&hhash, Input+64, 128);
/* wait until input completion callback */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_READY);
/* feeding last data and retrieve the computed digest */
HAL_HASH_SHA1_Accmlt_End_IT(&hhash, Input+192, 69, &Sha1output);
/* wait until digest computation callback */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_READY);




/* De-initialization */
HAL_HASH_DeInit(&hhash);
uint8_t Input[261] =
{0x54,0x68,0x65,0x20,0x68,0x61,0x73,0x68,
0x20,0x70,0x72,0x6f,0x63,0x65,0x73,0x73,
0x6f,0x72,0x20,0x69,0x73,0x20,0x61,0x20,
0x66,0x75,0x6c,0x6c,0x79,0x20,0x63,0x6f,
0x6d,0x70,0x6c,0x69,0x61,0x6e,0x74,0x20,
0x69,0x6d,0x70,0x6c,0x65,0x6d,0x65,0x6e,
0x74,0x61,0x74,0x69,0x6f,0x6e,0x20,0x6f,
0x66,0x20,0x74,0x68,0x65,0x20,0x73,0x65,
0x63,0x75,0x72,0x65,0x20,0x68,0x61,0x73,
0x68,0x20,0x61,0x6c,0x67,0x6f,0x72,0x69,
0x74,0x68,0x6d,0x20,0x28,0x53,0x48,0x41,
0x2d,0x31,0x29,0x2c,0x20,0x74,0x68,0x65,
0x20,0x4d,0x44,0x35,0x20,0x28,0x6d,0x65,
0x73,0x73,0x61,0x67,0x65,0x2d,0x64,0x69,
0x67,0x65,0x73,0x74,0x20,0x61,0x6c,0x67,
0x6f,0x72,0x69,0x74,0x68,0x6d,0x20,0x35,
0x29,0x20,0x68,0x61,0x73,0x68,0x20,0x61,
0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,
0x20,0x61,0x6e,0x64,0x20,0x74,0x68,0x65,
0x20,0x48,0x4d,0x41,0x43,0x20,0x28,0x6b,
0x65,0x79,0x65,0x64,0x2d,0x68,0x61,0x73,
0x68,0x20,0x6d,0x65,0x73,0x73,0x61,0x67,
0x65,0x20,0x61,0x75,0x74,0x68,0x65,0x6e,
0x74,0x69,0x63,0x61,0x74,0x69,0x6f,0x6e,
0x20,0x63,0x6f,0x64,0x65,0x29,0x20,0x61,
0x6c,0x67,0x6f,0x72,0x69,0x74,0x68,0x6d,
0x20,0x73,0x75,0x69,0x74,0x61,0x62,0x6c,
0x65,0x20,0x66,0x6f,0x72,0x20,0x61,0x20,
0x76,0x61,0x72,0x69,0x65,0x74,0x79,0x20,
0x6f,0x66,0x20,0x61,0x70,0x70,0x6c,0x69,
0x63,0x61,0x74,0x69,0x6f,0x6e,0x73,0x2e,
0x2a,0x2a,0x2a,0x20,0x53,0x54,0x4d,0x33,
0x32,0x20,0x2a,0x2a,0x2a};
uint8_t Msg3_Input[3] __attribute__ ((aligned (128)))= {
0x61, 0x62, 0x63};
uint8_t Sha1output[20]={0};
uint32_t sha1output_size;
hal_hash_suspended_context_t hash_ctx;

/* HASH Initialization */
HAL_HASH_Init(&hhash, HAL_HASH);
/* Configure HASH SHA1 algorithm */
hash_cfg.data_swapping  = HAL_HASH_DATA_SWAP_BYTE;
hash_cfg.algorithm = HAL_HASH_ALGO_SHA1;
HAL_HASH_SetConfig(&hhash, &hash_cfg);

/* process 1: Low-priority block computing in HASH processing mode */
HAL_HASH_Update_IT(&hhash, Input, 64);
HAL_HASH_RequestSuspendComputation(&hash);
/* wait until suspend callback is invoked */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_SUSPENDED);
/* Context saving operation */
HAL_HASH_SaveContext(&hhash, &hash_ctx);



/* process 2: High-priority block computing in HMAC processing mode */
hash_hmac_cfg.data_swapping  = HAL_HASH_DATA_SWAP_BYTE;
hash_hmac_cfg.algorithm = HAL_HASH_ALGO_SHA256;
hash_hmac_cfg.key_size_byte = 3;
hash_hmac_cfg.p_key = Msg3_Input;
HAL_HASH_HMAC_SetConfig(&hhash, &hash_hmac_cfg);
HAL_HASH_HMAC_Compute_IT(&hhash, Msg3_Input, 3, Sha1output, 32, &sha1output_size);
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);

/* Resume process 1 */
/* Context restoring operation */
HAL_HASH_RestoreContext(&hhash, &hash_ctx);
HAL_HASH_ResumeUpdate(&hhash);

/* feeding input buffer */
HAL_HASH_Update_IT(&hhash, Input+64, 128);
/* wait until input completion callback */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
/* feeding the last input buffer */
HAL_HASH_Update_IT(&hhash, Input+192, 69);
/* wait until input completion callback */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
/* retrieve the computed digest */
HAL_HASH_Finish(&hhash, Sha1output, 20, &sha1output_size, 1);
/* wait until digest computation callback */
while (HAL_HASH_GetState(&hhash) != HAL_HASH_STATE_IDLE);
/* De-initialization */
HAL_HASH_DeInit(&hhash);

Key changes

  1. HAL2 provides dedicated suspend/resume functions and a context structure for saving and restoring the HASH state.

  2. HAL2 uses unified APIs for HASH and HMAC configuration and computing, allowing switching between processes while preserving a suspended context.